//*****************************************************************************
//*****************************************************************************
// I2C Master Routines


//==============================================================
// I2C Definitions to include

// #define 	I2C_SCL			1
// #define 	I2C_SDA			0
// #define	I2C_PRT			GPFout
// #define	I2C_CFG			GPFcfg

// #define	_SDA				0
// #define	_SCL				1
 	
// #define	_I2C_InterruptPin		4		//PC4
//===============================================================

#ifdef _I2C_MasterSupport

#ifdef _SmallI2CMasterRoutines
//==============================================================================
//    Send start bit on I2C bus
//    uses GPIO, data, clk pins defined by I2C_SDA, and I2C_SCL
//    r0	= scratchpad reg
//    r6	= in: return address
//==============================================================================
I2cPutStart:
		inp	r1, I2C_CFG
		bis	r1, r1, I2C_SDA+8			//start = falling edge of data when clk high
		bic	r1, r1, I2C_SDA
		outp	r1, I2C_CFG

		jsr	r0, I2cWait
		jsr	r0, I2cWait

//		inp	r1, I2C_CFG
		bis	r1, r1, I2C_SCL+8			//falling edge of clk
		bic	r1, r1, I2C_SCL
		outp	r1, I2C_CFG
		
		jsr	r0, I2cWait

		jsr	r6, r6				//return


//==============================================================================
//    Send stop bit on I2C bus
//    uses GPIO, data, clk pins defined by I2C_SDA, and I2C_SCL
//    r0	= scratchpad reg
//    r2 	= out: 0x0000 No error
//    		 0x0001 NACK
//    		 0x0002 SDA held low
//    		 0x0004 SCL held low
//    		 0x0008 Timeout
//    r6	= in: return address
//==============================================================================
I2cPutStop:
		inp	r1, I2C_CFG				//stop = rising edge of data when clk high
		bis	r1, r1, I2C_SDA+8			//take data low
		bic	r1, r1, I2C_SDA
		bis	r1, r1, I2C_SCL+8			//take clock low
		bic	r1, r1, I2C_SCL
		outp	r1, I2C_CFG

		jsr	r0, I2cWait

//		inp	r1, I2C_CFG
		bic	r1, r1, I2C_SCL+8			//Release clock high
		outp	r1, I2C_CFG

		jsr	r0, I2cWait
		jsr	r0, I2cWait
	
	
		bic	r1, r1, I2C_SDA+8			//Release data high
		outp	r1, I2C_CFG

		jsr	r6, r6




//==============================================================================
//    Send data on I2C bus
//    uses GPIO, data, clk pins defined by I2C_SDA, and I2C_SCL
//    The bottom eight bits of r2 are sent.  
//    r0	= scratchpad reg
//    r1	= scratchpad reg
//    r2	= in: data to shift out MSB first
//    r2 	= out: 0x0000 No error
//    		 0x0001 NACK
//    		 0x0002 SDA held low
//    		 0x0004 SCL held low
//    		 0x0008 Timeout
//    r6	= in: return address
//==============================================================================
I2cPut:
	//r1 = bit counter
	//r2 = data to shift out
	//r0 = temp
	I2cPut_SetCounter:	
		mov	r1, 8					//Always send eight bits
		rol	r2, r2, 8				//Shift LSByte into MSByte
	I2cPut_ShiftRegister:
		add	r2, r2, r2				//shift left into carry
		bc	CC, I2cPut_ProgramZero

	I2cPut_ProgramOne:
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG
	
		rol	r0,r0,0
		rol	r0,r0,0
		rol	r0,r0,0
		rol	r0,r0,0
//		inp	r0, I2C_PRT				//Check that SDA is high.  
//		and 	r0, r0, 1<<I2C_SDA 		
//		bc 	ZC, I2cPut_CheckDh		
//		bis	r2, r2, 2				// SDA error
//	I2cPut_CheckDh:
		bra	I2cPut_GenerateClock

	I2cPut_ProgramZero:
		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SDA+8			//Take data low
		outp	r0, I2C_CFG

	I2cPut_GenerateClock:
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

//		inp	r0, I2C_PRT				//Check that SCL is high.  
//		and 	r0, r0, 1<<I2C_SCL 		
//		bc 	ZC, I2cPut_CheckCh	
//		bis	r2, r2, 3				// SCL error
//	I2cPut_CheckCh:
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

	I2cPut_NextBit:
		sub	r1, r1, 1
		bc	ZC, I2cPut_ShiftRegister

	I2cPut_GetAck:
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		inp	r0, I2C_PRT
		bis	r0, r0, I2C_SDA			//check for ACK(data = 0)
		bc	VS, I2cPut_Nack

	I2cPut_GotAck:
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		mov	r2, 0					//ACK return flag
		bic	r2,r2,15
		jsr	r6, r6				//return

	I2cPut_Nack:
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		bis	r2, r2, 15				//NACK return flag
		jsr	r6, r6
#else
//==============================================================================
//    Send start bit on I2C bus
//    uses GPIO, data, clk pins defined by I2C_SDA, and I2C_SCL
//    r0	= scratchpad reg
//    r6	= in: return address
//	Ncc	= Set: Bus error, Start Condition not generated
//		  Clear: Valid start generated
//==============================================================================
I2cPutStart:
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG
				
		jsr 	r0, I2cWait
		
		inp	r0, I2C_PRT				//Check that SDA and SCL are high (bus idle).  
		and 	r0, r0, 1<<I2C_SDA 		
		bc 	ZS, I2cPutStart_Error		

		inp	r0, I2C_PRT
		and 	r0, r0, 1<<I2C_SCL			
		bc 	ZS, I2cPutStart_Error

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SDA+8			//start = falling edge of data when clk high
		bic	r0, r0, I2C_SDA
		outp	r0, I2C_CFG

		jsr	r0, I2cWait
		jsr	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//falling edge of clk
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG
		
		jsr	r0, I2cWait

		bic	r0,r0,15
		jsr	r6, r6				//return

	I2cPutStart_Error:
		bis	r0,r0,15
		jsr	r6,r6


//==============================================================================
//    Send stop bit on I2C bus
//    uses GPIO, data, clk pins defined by I2C_SDA, and I2C_SCL
//    r0	= scratchpad reg
//    r2 	= out: 0x0000 No error
//    		 0x0001 NACK
//    		 0x0002 SDA held low
//    		 0x0004 SCL held low
//    		 0x0008 Timeout
//    r6	= in: return address
//==============================================================================
I2cPutStop:
		inp	r0, I2C_CFG				//stop = rising edge of data when clk high
		bis	r0, r0, I2C_SDA+8			//take data low
		bic	r0, r0, I2C_SDA
		bis	r0, r0, I2C_SCL+8			//take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr	r0, I2cWait

		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr	r0, I2cWait
		jsr	r0, I2cWait
	
		inp	r0, I2C_PRT				//Check that SCL is high.  
		and 	r0, r0, 1<<I2C_SCL 		
		bc 	ZC, I2cPutStop_CheckCh	
		bis	r2, r2, 3				// SCL error
	I2cPutStop_CheckCh:
		inp	r0, I2C_CFG			
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG

		jsr	r0, I2cWait
		jsr	r0, I2cWait
	
		inp	r0, I2C_PRT				//Check that SDA is high.  
		and 	r0, r0, 1<<I2C_SDA 		
		bc 	ZC, I2cPutStop_CheckDh		
		bis	r2, r2, 2				// SDA error
	I2cPutStop_CheckDh:
		inp	r0, I2C_CFG				//stop = rising edge of data when clk high
		bic	r0, r0, I2C_SDA+8			//Release data high
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr	r6, r6




//==============================================================================
//    Send data on I2C bus
//    uses GPIO, data, clk pins defined by I2C_SDA, and I2C_SCL
//    The bottom eight bits of r2 are sent.  
//    r0	= scratchpad reg
//    r1	= scratchpad reg
//    r2	= in: data to shift out MSB first (must be left alligned)
//    r2 	= out: 0x0000 No error
//    		 0x0001 NACK
//    		 0x0002 SDA held low
//    		 0x0004 SCL held low
//    		 0x0008 Timeout
//    r6	= in: return address
//==============================================================================
I2cPut:
	//r1 = bit counter
	//r2 = data to shift out
	//r0 = temp
	I2cPut_SetCounter:	
		mov	r1, 8					//Always send eight bits
		rol	r2, r2, 8				//Shift LSByte into MSByte
	I2cPut_ShiftRegister:
		add	r2, r2, r2				//shift left into carry
		bc	CC, I2cPut_ProgramZero

	I2cPut_ProgramOne:
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG
	
		rol	r0,r0,0
		rol	r0,r0,0
		rol	r0,r0,0
		rol	r0,r0,0
		
		inp	r0, I2C_PRT				//Check that SDA is high.  
		and 	r0, r0, 1<<I2C_SDA 		
		bc 	ZC, I2cPut_CheckDh		
		bis	r2, r2, 2				// SDA error
		bra	I2cPut_Error
	I2cPut_CheckDh:
		bra	I2cPut_GenerateClock10

	I2cPut_ProgramZero:
		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SDA+8			//Take data low
		outp	r0, I2C_CFG

	I2cPut_GenerateClock:
		jsr 	r0, I2cWait
		I2cPut_GenerateClock10:

		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		inp	r0, I2C_PRT				//Check that SCL is high.  
		and 	r0, r0, 1<<I2C_SCL 		
		bc 	ZC, I2cPut_CheckCh	
		bis	r2, r2, 3				// SCL error
		bra	I2cPut_Error
	I2cPut_CheckCh:
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

	I2cPut_NextBit:
		sub	r1, r1, 1
		bc	ZC, I2cPut_ShiftRegister

	I2cPut_GetAck:
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		inp	r0, I2C_PRT
		bix	r0, r0, I2C_SDA			//check for ACK(data = 0)
		bc	VS, I2cPut_Nack

	I2cPut_GotAck:
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		mov	r2, 0					//ACK return flag
		bic	r2,r2,15
		jsr	r6, r6				//return

	I2cPut_Nack:
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		bis	r2, r2, 15				//NACK return flag
		jsr	r6, r6

	I2cPut_Error:
		bis	r2,r2,15
		jsr	r6,r6

//==============================================================================
//    Get data on I2C bus
//    uses GPIO, data, clk pins defined by I2C_SDA, and I2C_SCL
//    Assumes SCL is low on start
//    r0	= scratchpad reg
//    r1	= scratchpad reg
//    r2 	= out: Data from Slave
//    r6	= in: return address
//==============================================================================
I2cGet:
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG

	//r1 = bit counter
	//r2 = data shifted in
	//r0 = temp
	I2cGet_SetCounter:	
		mov	r1, 8					//Always get eight bits
		mov	r2, 0

	I2cGet_NextBit:
		jsr 	r0, I2cWait
		
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		rol	r2, r2, 1				// rotate up to prepare for next bit
		inp	r0, I2C_PRT
		and	r0, r0, 1<<I2C_SDA		// Mask data bit
		rol	r0, r0, -I2C_SDA			// Correct for pin offset
		ior	r2, r2, r0				// Combine
		
		jsr 	r0, I2cWait
		
		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		sub	r1, r1, 1
		bc	ZC, I2cGet_NextBit

		// Send ACK
		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SDA+8			//Take data low
		bic	r0, r0, I2C_SDA
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG
		
		jsr 	r0, I2cWait
		
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG
		
		jsr	r6, r6


//==============================================================================
//    Get data on I2C bus
//    uses GPIO, data, clk pins defined by I2C_SDA, and I2C_SCL
//    Assumes SCL is low on start
//    r0	= scratchpad reg
//    r1	= scratchpad reg
//    r2 	= out: Data from Slave
//    r6	= in: return address
//==============================================================================
I2cGetNack:
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG

	//r1 = bit counter
	//r2 = data shifted in
	//r0 = temp
	I2cGetNack_SetCounter:	
		mov	r1, 8					//Always get eight bits
		mov	r2, 0

	I2cGetNack_NextBit:
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		rol	r2, r2, 1				// rotate up to prepare for next bit
		inp	r0, I2C_PRT
		and	r0, r0, 1<<I2C_SDA		// Mask data bit
		rol	r0, r0, -I2C_SDA			// Correct for pin offset
		ior	r2, r2, r0				// Combine

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		sub	r1, r1, 1
		bc	ZC, I2cGetNack_NextBit

		
		// Send NACK
		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SDA+8			//Release data high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bic	r0, r0, I2C_SCL+8			//Release clock high
		outp	r0, I2C_CFG

		jsr 	r0, I2cWait
		jsr 	r0, I2cWait

		inp	r0, I2C_CFG
		bis	r0, r0, I2C_SCL+8			//Take clock low
		bic	r0, r0, I2C_SCL
		outp	r0, I2C_CFG
		
		jsr	r6, r6


#endif
//==============================================================================
// The number of NOPs here determines I2C freq. 
// The wait should equal 1/4 of I2C clock period
//==============================================================================
I2cWait: 						
		rol	r0, r0, 0				//nop
		rol	r0, r0, 0				//nop
		rol	r0, r0, 0				//nop
		rol	r0, r0, 0				//nop
		rol	r0, r0, 0				//nop
		rol	r0, r0, 0				//nop
		rol	r0, r0, 0				//nop
				
		jsr	r0, r0
		
#endif		
//*****************************************************************************
//*****************************************************************************
// I2C Slave Routines
		
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The following I2C routines are avaliable
//	I2C_LookForStart
//	I2C_GetByte
//	I2C_SendByte
//	I2C_SendACK
//	I2C_GetACK
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		Subroutine: I2C_LookForStart
//		This routine must be called every 4 us to ensure that
//		the start term is caught.
//		r0	= scrambled
//		r1	= scrambled
//		if a start is detected then r2 and r3 are also used
//		r6	= in: return address
//		r7	= stack pointer
//		N cc - Set = Start found
//		N cc - Clear = No Start
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I2C_LookForStart:
		inp	r0, I2C_PRT
		bc	VS, NoStartDetected		//for start SDA should be low
		bix	r1, r0, _SCL			//and SCL should be high
		bc	VC, NoStartDetected
		ld	r1, LastI2Cstate
		and	r1, r1, 0x0003
		sub	r1, r1, 0x0003			//and both SDA and SCL should have been 
		bc	NE, NoStartDetected		//high last time
	StartDetected:
		st	r0, LastI2Cstate
		bis	r0, r0, 15
		jsr	r5, r5
	NoStartDetected:
		st	r0, LastI2Cstate
		bic	r0, r0, 15
		jsr	r5, r5

	
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		Subroutine: I2C_GetByte
//		It will get 8 bits from the I2C bus.
//		r0	= scrambled
//		r1	= out: I2C data 
//		r2	= scrambled
//		r6	= in: return address
//		r7	= stack pointer
//		N cc - Set = Stop Detected
//		N cc - Clear = Data Received
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
I2C_GetByte:
	GetByte_CheckSCL_Low10:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//wait for SCL to go Low
		bc	VS, GetByte_CheckSCL_Low10
		
		mov	r0, 8					//setup bit counter
		mov	r1, 0					//clear r1
		
	GetByte_MainLoop:
		rol	r1, r1, 1				//shift data
	GetByte_CheckSCL_High:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//wait for SCL to go high
		bc	VC, GetByte_CheckSCL_High
		bix	r3, r2, _SDA
		bc	VC, GetByte_WatchForStop	//if data is already high then it is not a stop
		mov	r2, 80				//setup timeout
	//SCL and SDA are high, also idle condition
	GetByte_CheckSCL_Low:
		sub	r2, r2, 1
		bc	ZS, GetByte_StopDetected
		inp	r3, I2C_PRT
		bix	r3, r3, _SCL			//wait for SCL to go Low
		bc	VS, GetByte_CheckSCL_Low
		bis	r2, r2, 0				//restore data
		bra	GetByte_NoStopDetected
		
	GetByte_WatchForStop:
		inp	r3, I2C_PRT
		bix	r3, r3, _SCL			//wait for SCL to go Low
		bc	VC, GetByte_NoStopDetected
		bix	r3, r3, _SDA			//or SDA to go high
		bc	VC, GetByte_WatchForStop
	//Stop Detected
	GetByte_StopDetected:
		bis	r0, r0, 15				//set Ncc
		jsr	r6, r6
		
	GetByte_NoStopDetected:
		and	r2, r2, 0x0001			//Mask off data bit
		ior	r1, r1, r2				//add in new bit
		sub	r0, r0, 1				//decrement bit counter
		bc	ZC, GetByte_MainLoop
	//valid byte from master
		bic	r0, r0, 15				//clear Ncc
		jsr	r6, r6


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		Subroutine: I2C_SendByte
//		This routine should be called when SCL is low.
//		It will send 8 bits to the I2C bus.
//		r0	= scrambled
//		r1	= in: I2C data 
//		r2	= scrambled
//		r3	= scrambled
//		r6	= in: return address
//		r7	= stack pointer
//		N cc - Set = Error/Lost Arbitration
//		N cc - Clear = Data was sent
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
I2C_SendByte:
		mov	r0, 8					//setup bit counter
	SendByte_CheckSCL10:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//wait for SCL to go low
		bc	VS, SendByte_CheckSCL10
		
	SendByte_NextBit:	
		inp	r3,I2C_CFG
		rol	r1,r1,1
		bix	r2,r1,8
		bc	VS,SendByte_put1
		bis	r3,r3,_SDA+8
		bic	r3,r3,_SDA
		bra	SendByte_put0
	SendByte_put1:
		bic	r3,r3,_SDA+8
	SendByte_put0:
		outp	r3,I2C_CFG

	SendByte_CheckSCL20:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//wait for SCL to go high
		bc	VC, SendByte_CheckSCL20
				
	SendByte_CheckSCL30:
		inp	r3, I2C_PRT
		bc	VS, DataIsVlaid
		bix	r2, r1, 8				//if the line is low, make sure we are the one driving it
//*		bc	VC, DataIsInvalid
	DataIsVlaid:
		bix	r3, r3, _SCL			//Wait for SCL to go low
		bc	VS, SendByte_CheckSCL30	
		sub	r0, r0, 1
		bc	ZC, SendByte_NextBit
		
		inp	r3, I2C_CFG
		bic	r3, r3, _SDA+8			//release the SDA line
		outp	r3, I2C_CFG		
		
		bic	r0, r0, 15				//clear error flag
		jsr	r6, r6		
		
	DataIsInvalid:
		inp	r3, I2C_CFG
		bic	r3, r3, _SDA+8			//release the SDA line
		outp	r3, I2C_CFG	
		
		bis	r0, r0, 15				//set error flag
		jsr	r6, r6
		
		
		
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		Subroutine: I2C_SendACK
//		It will send an ACK to the master.
//		r2	= scrambled
//		r6	= in: return address
//		r7	= stack pointer
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
I2C_SendACK:
	SendACK_CheckSCL_Low:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//Ensure that SCL is Low
		bc	VS, SendACK_CheckSCL_Low
		
	SendACK_CheckSDA_High:
		inp	r2, I2C_PRT				//Ensure that the bus is free
		bc	VC, SendACK_CheckSDA_High
		
		inp	r2, I2C_CFG
		bis	r2, r2, _SDA+8			//set SDA as output driving low
		bic	r2,r2,_SDA
		outp	r2, I2C_CFG

	SendACK_CheckSCL_High:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//wait for SCL to go high
		bc	VC, SendACK_CheckSCL_High
		
	SendACK_CheckSCL_Low10:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//wait for SCL to go low
		bc	VS, SendACK_CheckSCL_Low10
		
		rol	r2,r2,0
		
		inp	r2, I2C_CFG
		bic	r2, r2, _SDA+8			//release SDA
		outp	r2, I2C_CFG

		jsr	r6, r6
		
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		Subroutine: I2C_GetACK
//		This routine should be called when SCL is low.
//		It will get an ACK from the master.
//		r2	= scrambled
//		r6	= in: return address
//		r7	= stack pointer
//		N cc - Set = NACK received
//		N cc - Clear = ACK received
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
I2C_GetACK:
	GetACK_CheckSCL_Low:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//wait for SCL to go low
		bc	VS, GetACK_CheckSCL_Low
	GetACK_CheckSCL_High:
		inp	r2, I2C_PRT
		bix	r2, r2, _SCL			//Wait for SCL to go high
		bc	VC, GetACK_CheckSCL_High		

		inp	r2, I2C_PRT
		bc	VS, GetACK_NACKReceived
		
		bic	r2, r2, 15
		jsr	r6, r6
		
	GetACK_NACKReceived:
		bis	r2, r2, 15
		jsr	r6, r6